package com.slt.developkitweb.crm;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j
public class CrmHttpCli {

    private static final String CHARSET = "UTF-8";                         //编码格式
    private static final String PREFIX = "--";                            //前缀
    private static final String CONTENT_TYPE = "multipart/form-data";     //内容类型
    private static final String LINE_END = "\r\n";

    private final String URL;
    private final String PATH;

    public CrmHttpCli(String URL,String PATH){
        this.URL = URL;
        this.PATH = PATH;
    }

    public static Boolean downloadFile(String fileUrl,String saveDir,String fileName){
        long startTime = System.currentTimeMillis();
        HttpURLConnection connection = null;
        InputStream is = null;
        FileOutputStream os = null;
        try {
            System.out.println("调用请求 url\t"+fileUrl);
            URL url = new URL(fileUrl);
            connection = (HttpURLConnection)url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(15000);

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_CLIENT_TIMEOUT) {
                System.out.println("请求超时");
            } else if (responseCode == HttpURLConnection.HTTP_OK) {

                // 获取输入流
                is = connection.getInputStream();

                // 创建输出流
                os = new FileOutputStream(new File(saveDir+fileName));

                // 从输入流读取数据并写入输出流
                int bytesRead;
                byte[] buffer = new byte[4096];
                while ((bytesRead = is.read(buffer)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
            }
        } catch (MalformedURLException e) {
            System.out.println("格式错误的URL异常");
            e.printStackTrace();
            return  false;
        } catch (IOException e) {
            if (e instanceof java.net.SocketTimeoutException) {
                System.out.println("响应超时");
                e.printStackTrace();
            }
            System.out.println("IO异常");
            e.printStackTrace();
            return  false;
        } catch (Exception e) {
            System.out.println("系统异常");
            e.printStackTrace();
            return  false;
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    System.out.println("关闭流资源 IO异常");
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    System.out.println("关闭流资源 IO异常");
                    e.printStackTrace();
                }
            }
            if (connection != null) connection.disconnect();
            System.out.println("接口调用请求 耗时\t"+calculateRuntime(startTime));
        }
        return  true;
    }

    //请求方法
    public String httpPost(String body) {
        long startTime = System.currentTimeMillis();
        HttpURLConnection connection = null;
        InputStream is = null;
        OutputStream os = null;
        BufferedReader br = null;
        String result = null;
        try {
            System.out.println("调用请求 url\t"+URL+PATH);
            System.out.println("调用请求 body\t"+body);
            URL url = new URL(URL + PATH);
            connection = (HttpURLConnection)url.openConnection();
            connection.setRequestMethod("POST");
            connection.setConnectTimeout(300000);
            connection.setReadTimeout(60000);

            connection.setDoOutput(true);
            connection.setDoInput(true);
//            connection.setRequestProperty("Source", "openapi");
            connection.setRequestProperty("Content-Type", "application/json");
            os = connection.getOutputStream();
            os.write(body.getBytes(StandardCharsets.UTF_8));

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_CLIENT_TIMEOUT) {
                System.out.println("请求超时");
            } else if (responseCode == HttpURLConnection.HTTP_OK) {
                is = connection.getInputStream();
                br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));

                StringBuffer sbf = new StringBuffer();
                String temp;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            System.out.println("格式错误的URL异常");
            e.printStackTrace();
        } catch (IOException e) {
            if (e instanceof java.net.SocketTimeoutException) {
                System.out.println("响应超时");
                e.printStackTrace();
            }
            System.out.println("IO异常");
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("系统异常");
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    System.out.println("关闭流资源 IO异常");
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    System.out.println("关闭流资源 IO异常");
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    System.out.println("关闭流资源 IO异常");
                    e.printStackTrace();
                }
            }
            if (connection != null) connection.disconnect();
            System.out.println("接口调用请求 耗时\t"+calculateRuntime(startTime));
        }
        return result;
    }


    public String uploadFile(final JSONObject strParams, final Map<String, File> fileParams) throws Exception{
        long startTime = System.currentTimeMillis();
        String BOUNDARY = String.valueOf(UUID.randomUUID());  //边界标识 随机生成
        HttpURLConnection connection = null;

        InputStream is = null;
        BufferedReader br = null;
        String result = null;
        DataOutputStream dos = null;

        String path = URL+PATH;

        try {
            log.info("调用请求 url\t"+path);
            log.info("调用请求 body\t"+strParams);
            log.info("调用请求 files\t"+(fileParams != null?fileParams.size():0));

            URL url = new URL(path);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setReadTimeout(600000);
            connection.setConnectTimeout(300000);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);//Post 请求不能使用缓存
            //设置请求头参数
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Charset", CHARSET);
            connection.setRequestProperty("Accept-Charset", CHARSET);
            connection.setRequestProperty("Content-Type", CONTENT_TYPE + ";charset=" + CHARSET +";boundary=" + BOUNDARY);
            /**
             * 请求体
             */
            //上传参数
            dos = new DataOutputStream(connection.getOutputStream());
            //getStrParams()为一个
            if(strParams != null && !strParams.isEmpty()){
                StringBuilder strSb = new StringBuilder();
                for (Map.Entry<String, Object> entry : strParams.entrySet() ){
                    strSb.append(PREFIX)
                            .append(BOUNDARY)
                            .append(LINE_END)
                            .append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END)
                            .append("Content-Type: text/plain; charset=" + CHARSET + LINE_END)
                            .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                            .append(LINE_END)// 参数头设置完以后需要两个换行，然后才是参数内容
                            .append(entry.getValue())
                            .append(LINE_END);
                }
                dos.write(strSb.toString().getBytes(CHARSET));
                dos.flush();
            }

            writeFiles(fileParams,dos,BOUNDARY);
            //请求结束标志
            String end = PREFIX + BOUNDARY + PREFIX + LINE_END;
            dos.write(end.getBytes(CHARSET));
            dos.flush();
            dos.close();

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_CLIENT_TIMEOUT) {
                log.error("请求超时");
            } else if (responseCode == HttpURLConnection.HTTP_ENTITY_TOO_LARGE) {
//                throw new SysException("请求失败,请求实体过大");
            } else if (responseCode == HttpURLConnection.HTTP_OK) {
                is = connection.getInputStream();
                br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));

                StringBuffer sbf = new StringBuffer();
                String temp;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                }
                result = sbf.toString();

                log.info("请求原始返回:{}", result);
            }else {
                log.error("请求返回编码:{}", responseCode);

//                throw new SysException("请求失败,返回编码:" + responseCode);
            }
        } catch (Exception e) {
            throw e;
//            throw new SysException("系统异常:" + e.getMessage());
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    log.error("关闭流资源 IO异常:{}",e.getMessage(), e);
                }
            }
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    log.error("关闭流资源 IO异常:{}",e.getMessage(), e);
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    log.error("关闭流资源 IO异常:{}",e.getMessage(), e);
                }
            }
            if (connection != null) connection.disconnect();
            log.info("接口调用请求 耗时\t"+calculateRuntime(startTime));
        }
        return result;
    }

    //传文件
    private static void writeFiles(Map<String, File> fileParams, OutputStream os, String BOUNDARY) throws IOException {
        for(Map.Entry<String, File> file: fileParams.entrySet()){
            InputStream is = null;

            try {
                StringBuilder requestParams = new StringBuilder();
                requestParams.append(PREFIX).append(BOUNDARY).append(LINE_END);
                requestParams.append("Content-Disposition: form-data; name=\""+file.getKey()+"\";").append("filename=\"").append(file.getValue().getPath()).append("\"").append(LINE_END);
                requestParams.append("Content-Type: application/octet-stream").append(LINE_END);
                requestParams.append("Content-Transfer-Encoding: 8bit").append(LINE_END);
                requestParams.append(LINE_END);
                os.write(requestParams.toString().getBytes());

                is =  new FileInputStream(file.getValue());

                byte [] buff =  new byte[8192];

                int len=0;

                while( (len=is.read(buff))!=-1){
                    os.write(buff,0,len);
                }
                os.write(LINE_END.getBytes());
                os.flush();
            } finally{

            }

        }

    }

    //传请求参数
//    private static void writeParams(Map<String, String> params, OutputStream os,String BOUNDARY) throws IOException {
//        if (!MapUtils.isEmpty(params)) {
//            StringBuilder requestParams = new StringBuilder();
//            for (Map.Entry<String, String> entry : params.entrySet()) {
//
//                requestParams.append(PREFIX).append(BOUNDARY).append(LINE_END);//开始标识
//                requestParams.append("Content-Disposition: form-data; name=\"").append(entry.getKey()).append("\"").append(LINE_END);//分割符
//                requestParams.append("Content-Type: text/plain; charset=UTF-8").append(LINE_END);
//                requestParams.append("Content-Transfer-Encoding: 8bit").append(LINE_END);
//                requestParams.append(LINE_END);
//                requestParams.append(entry.getValue());
//                requestParams.append(LINE_END);
//
//            }
//            //os.write(requestParams.toString().getBytes());//中文乱码
//            os.write(requestParams.toString().getBytes("UTF-8"));//解决中文乱码
//            os.flush();
//        }
//    }

    public static String calculateRuntime(long startTime){
        return calculateRuntime(startTime,System.currentTimeMillis());
    }

    public static String calculateRuntime(long startTime,long endTime){
        long tempTime = (endTime - startTime);
        return (((tempTime/86400000)>0)?((tempTime/86400000)+"d "):"")+
                ((((tempTime/86400000)>0)||((tempTime%86400000/3600000)>0))?((tempTime%86400000/3600000)+"h "):(""))+
                ((((tempTime/3600000)>0)||((tempTime%3600000/60000)>0))?((tempTime%3600000/60000)+"m "):(""))+
                ((((tempTime/60000)>0)||((tempTime%60000/1000)>0))?((tempTime%60000/1000)+"s "):(""))+
                ((tempTime%1000)+"ms");
    }

    public static void main(String[] args) throws Exception {
        CrmHttpCli crmHttpCli = new CrmHttpCli("http://localhost:8080/test/", "testCrmFile");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appId","123");
        Map map = new HashMap();
        String filePath = "C:\\Users\\EDY\\Desktop\\crm\\C端用户信息.csv";
        map.put("perUserFile",new File(filePath));
        crmHttpCli.uploadFile(jsonObject,map);
    }
}
